package com.test.mybatis.factory;

import com.test.mybatis.config.Configuration;
import com.test.mybatis.config.MappedStatement;
import com.test.mybatis.session.DefaultSqlSession;
import com.test.mybatis.session.SqlSession;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class DefaultSqlSessionFactory implements SqlSessionFactory {

    // 希望Configuration是单例并且唯一
    private final Configuration configuration = new Configuration();
    // xml文件存放位置
    private final String MAPPER_CONFIG_LOCATION = "mapper";
    // 数据库信息存放位置
    private static final String DB_CONFIG_FILE = "mybatis.properties";

    public DefaultSqlSessionFactory() {
        loadDBInfo();
        loadMapperInfo();
    }

    private void loadDBInfo() {

        try {
            InputStream db = this.getClass().getClassLoader().getResourceAsStream(DB_CONFIG_FILE);
            Properties p = new Properties();
            p.load(db);

            // 将配置信息写入到Configuration对象
            configuration.setJdbcDriver(p.getProperty("jdbc_driver"));
            configuration.setJdbcUrl(p.getProperty("jdbc_url"));
            configuration.setJdbcUsername(p.getProperty("jdbc_username"));
            configuration.setJdbcPassword(p.getProperty("jdbc_password"));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void loadMapperInfo() {
        try {
            URL resource = this.getClass().getClassLoader().getResource(MAPPER_CONFIG_LOCATION);
            File mappers = new File(resource.getFile());

            if (mappers.isDirectory()) {
                File[] files = mappers.listFiles();
                for (File file : files) {
                    loadMapperInfo(file);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void loadMapperInfo(File file) {
        try {
            SAXReader reader = new SAXReader();
            Document document = reader.read(file);

            // 获取根节点元素对象<mapper>
            Element element = document.getRootElement();

            // 获取命名空间namespace
            String namespace = element.attribute("namespace").getValue();

            // 获取select insert update delete子节点列表
            List<Element> selects = element.elements("select");
            List<Element> inserts = element.elements("insert");
            List<Element> updates = element.elements("update");
            List<Element> deletes = element.elements("delete");

            List<Element> all = new ArrayList<>();
            all.addAll(selects);
            all.addAll(inserts);
            all.addAll(updates);
            all.addAll(deletes);

            for (Element ele : all) {
                MappedStatement mappedStatement = new MappedStatement();
                String id = ele.attribute("id").getData().toString();
                String resultType = ele.attribute("resultType").getData().toString();
                String sql = ele.getData().toString();

                mappedStatement.setId(namespace + "." + id);
                mappedStatement.setResultType(resultType);
                mappedStatement.setNamespace(namespace);
                mappedStatement.setSql(sql);

                configuration.getMappedStatement().put(namespace + "." + id, mappedStatement);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public SqlSession openSession() {
        return new DefaultSqlSession(configuration);
    }
}
